package cn.iocoder.yudao.module.trade.convert.order;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.api.tradedelivery.dto.TradeOrderDeliveryDTO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper
public interface TradeOrderConvert {

    TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class);

    @Mappings({
        @Mapping(target = "userId", source = "userId"),
        @Mapping(target = "weight", source = "createReqVO.weight"),
        @Mapping(target = "orderPrice", source = "createReqVO.livePrice"),
        @Mapping(target = "userRemark", source = "createReqVO.remark"),
        @Mapping(target = "orderType", source = "createReqVO.transactionType"),
        @Mapping(target = "metalType", source = "createReqVO.metalType"),
        @Mapping(target = "depositPriceConf", source = "createReqVO.metalConf.depositWeight"),
        @Mapping(target = "delayFeeConf", source = "createReqVO.metalConf.delayFee"),
        @Mapping(target = "processConf", source = "createReqVO.metalConf.processingFee"),
    })
    TradeOrderDO convert(Long userId, AppTradeOrderOrderCreateReqVO createReqVO, TradePriceCalculateRespBO calculateRespBO);

    @Mappings({
        @Mapping(target = "id", source = "orderNo"),
        @Mapping(target = "no", source = "orderNo"),
        @Mapping(target = "userId", source = "userId"),
        @Mapping(target = "userRemark", source = "userRemark"),
        @Mapping(target = "status", source = "status"),
        @Mapping(target = "cancelTime", source = "cancelTime"),
        @Mapping(target = "remark", source = "remark"),
        @Mapping(target = "payOrderId", source = "payOrderId"),
        @Mapping(target = "payStatus", expression = "java(orderDO.getPayStatus() != null && orderDO.getPayStatus() == 1)")
    })
    TradeOrderRespDTO convert(TradeOrderDO orderDO);

    TradePriceCalculateReqBO convert(AppTradeOrderOrderReqVO settlementReqVO);

    @Mappings({
        @Mapping(target = "userId", source = "userId")
    })
    TradePriceCalculateReqBO convert(Long userId, AppTradeOrderOrderReqVO settlementReqVO);

    default AppTradeOrderOrderRespVO convert(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) {
        AppTradeOrderOrderRespVO respVO = convert0(calculate, address);
        if (address != null) {
            respVO.getMemberAddress().setAreaName(AreaUtils.format(address.getAreaId()));
        }
        return respVO;
    }

    default AppTradeOrderOrderRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) {
        AppTradeOrderOrderRespVO res = new AppTradeOrderOrderRespVO();
        res.setType(calculate.getOrderType());
        res.setPrice(convertPrice(calculate));
        if (address != null) {
            res.setMemberAddress(AppTradeOrderOrderRespVO.Address.builder()
                    .id(address.getId())
                    .name(address.getName())
                    .mobile(address.getMobile())
                    .areaId(address.getAreaId())
                    .detailAddress(address.getDetailAddress())
                    .build());
        }
        return res;
    }

    AppTradeOrderOrderRespVO.Price convertPrice(TradePriceCalculateRespBO calculate);

    @Mapping(target = "content", source = "content")
    List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);

    // 以下方法创建TradeOrderDeliveryDO而非修改TradeOrderDO
    @Mappings({
        @Mapping(target = "orderNo", source = "id"),
        @Mapping(target = "name", source = "receiverName"),
        @Mapping(target = "mobile", source = "receiverMobile"),
        @Mapping(target = "areaId", source = "receiverAreaId"),
        @Mapping(target = "detailAddress", source = "receiverDetailAddress")
    })
    TradeOrderDeliveryDO convertToDelivery(TradeOrderUpdateAddressReqVO reqVO);

    @Mappings({
        @Mapping(target = "orderNo", source = "no"),
        @Mapping(target = "discountPrice", source = "adjustPrice")
    })
    TradeOrderDO convert(TradeOrderUpdatePriceReqVO reqVO);

    @Mappings({
        @Mapping(target = "orderNo", source = "no"),
        @Mapping(target = "remark", source = "remark")
    })
    TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);

    @Named("convertList04")
    @Mappings({
        @Mapping(target = "id", source = "orderNo"),
        @Mapping(target = "no", source = "orderNo"),
        @Mapping(target = "payStatus", expression = "java(metals.getPayStatus() != null && metals.getPayStatus() == 1)")
    })
    TradeOrderRespDTO convertItem(TradeOrderDO metals);

    @Named("convertList04")
    default List<TradeOrderRespDTO> convertList04(List<TradeOrderDO> list) {
        return CollectionUtils.convertList(list, this::convertItem);
    }

    @Mappings({
        @Mapping(target = "appKey", source = "tradeOrderProperties.payAppKey"),
        @Mapping(target = "orderNo", source = "order.orderNo"),
        @Mapping(target = "weight", source = "order.weight"),
        @Mapping(target = "price", source = "calculateRespBO.payPrice"),
        @Mapping(target = "processPrice", source = "calculateRespBO.producePrice"),
        @Mapping(target = "additionalPrice", source = "calculateRespBO.additionalPrice"),
        @Mapping(target = "payType", source = "calculateRespBO.payType"),
        @Mapping(target = "orderType", source = "order.orderType"),
        @Mapping(target = "metalPrice", source = "order.metalPrice"),
        @Mapping(target = "expireTime", source = "order.expireTime"),
    })
    PayOrderCreateReqDTO convert(TradeOrderDO order, TradeOrderProperties tradeOrderProperties, TradePriceCalculateRespBO calculateRespBO);

    @Mappings({
        @Mapping(target = "name", source = "address.name"),
        @Mapping(target = "mobile", source = "address.mobile"),
        @Mapping(target = "areaId", source = "address.areaId"),
        @Mapping(target = "detailAddress", source = "address.detailAddress"),
        @Mapping(target = "orderNo", source = "orderNo")
    })
    TradeOrderDeliveryDO convertDelivery(MemberAddressRespDTO address, String orderNo);
    @Mapping(source = "areaId", target = "areaName",  qualifiedByName = "convertAreaIdToAreaName")
    TradeOrderDeliveryRespVO convertDelivery(TradeOrderDeliveryDO address);
    @Mapping(source = "areaId", target = "areaName",  qualifiedByName = "convertAreaIdToAreaName")
    TradeOrderDeliveryDTO convertDeliveryDTO(TradeOrderDeliveryDO address);
    @Named("convertAreaIdToAreaName")
    default String convertAreaIdToAreaName(Integer areaId) {
        return AreaUtils.format(areaId);
    }

    @Mappings({
        @Mapping(target = "name", source = "address.name"),
        @Mapping(target = "mobile", source = "address.phone"),
        @Mapping(target = "areaId", source = "address.areaId"),
        @Mapping(target = "detailAddress", source = "address.detailAddress"),
        @Mapping(target = "orderNo", source = "orderNo")
    })
    TradeOrderDeliveryDO convertDelivery(DeliveryPickUpStoreDO address, String orderNo);

    PageResult<AppTradeOrderPageRespVO> convertPage(PageResult<TradeOrderDO> pageResult);

    @Mappings({
            @Mapping(target = "payStatus", source = "payOrder.status"),
            @Mapping(target = "status", source = "order.status"),
            @Mapping(target = "weight", source = "order.weight"),
            @Mapping(target = "metalPrice", source = "order.metalPrice"),
            @Mapping(target = "exchangeWeight", source = "order.exchangeWeight"),
            @Mapping(target = "convertWeight", source = "order.convertWeight"),
            @Mapping(target = "orderNo", source = "order.orderNo"),
    })
    AppTradeOrderDetailRespVO convertDetail(TradeOrderDO order, PayOrderRespDTO payOrder);


    // TODO: 2025/4/4
    //        tradeOrderDetailRespVO.setReceiverAreaName();
    //        tradeOrderDetailRespVO.setPickUpStoreId();
    //        tradeOrderDetailRespVO.setDeliveryTemplateId();
    //        tradeOrderDetailRespVO.setLogisticsId();
    //        tradeOrderDetailRespVO.setLogisticsNo();
    //        tradeOrderDetailRespVO.setDeliveryTime();
    //        tradeOrderDetailRespVO.setReceiveTime();
    //        tradeOrderDetailRespVO.setReceiverName();
    //        tradeOrderDetailRespVO.setReceiverMobile();
    //        tradeOrderDetailRespVO.setReceiverAreaId();
    //        tradeOrderDetailRespVO.setReceiverDetailAddress();
    @Mappings({
            @Mapping(target = "userId", source = "order.userId"),
            @Mapping(target = "weight", source = "order.weight"),
            @Mapping(target = "orderNo", source = "order.orderNo"),
            @Mapping(target = "createTime", source = "order.createTime"),
            @Mapping(target = "status", source = "order.status"),
            @Mapping(target = "cancelTime", source = "order.cancelTime"),
            @Mapping(target = "remark", source = "order.remark"),
            @Mapping(target = "userRemark", source = "order.userRemark"),
            @Mapping(target = "metalPrice", source = "payOrder.metalPrice"),
            @Mapping(target = "payOrderId", source = "payOrder.id"),
            @Mapping(target = "exchangeWeight", source = "order.exchangeWeight"),
            @Mapping(target = "convertWeight", source = "order.convertWeight"),
            @Mapping(target = "purity", source = "order.purity"),
            @Mapping(target = "settleTime", source = "order.settleTime"),
            @Mapping(target = "logs", source = "logList")
    })
    TradeOrderDetailRespVO convert(TradeOrderDO order, PayOrderRespDTO payOrder, List<TradeOrderLogDO> logList);
}
